package com.frskycockpit.bluetooth;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ArrayAdapter;
import android.widget.Toast;

public class BluetoothSerial {
	Context mContext;
	Handler mHandler;
	BluetoothAdapter mBluetoothAdapter;
	BluetoothSocket mmSocket;
	BluetoothDevice mmDevice;
	Set<BluetoothDevice> mmPairedDevices;
	OutputStream mmOutputStream;
	InputStream mmInputStream;
	Thread workerThread;
	volatile boolean stopWorker;
	byte[] readBuffer;
	BluetoothSerialCallback mBluetoothSerialCallback;

	public BluetoothSerial(Context context, Handler handler,
			BluetoothSerialCallback bluetoothSerialCallback) {
		mContext = context;
		mHandler = handler;
		mBluetoothSerialCallback = bluetoothSerialCallback;
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
	}

	public boolean findBT() {
		if (mBluetoothAdapter == null) {
			Toast.makeText(mContext, "No bluetooth adapter available",
					Toast.LENGTH_LONG).show();
			return false;
		}

		if (!mBluetoothAdapter.isEnabled()) {
			Toast.makeText(mContext, "Not enable bluetooth adapter",
					Toast.LENGTH_LONG).show();
			return false;
		}

		mBluetoothSerialCallback.OnBluetoothOpen();

		mmPairedDevices = mBluetoothAdapter.getBondedDevices();
		final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
				mContext, android.R.layout.select_dialog_singlechoice);
		if (mmPairedDevices.size() > 0) {
			for (BluetoothDevice device : mmPairedDevices) {
				arrayAdapter.add(device.getName());
			}
			displayList(arrayAdapter);
			return true;
		}
		return false;
	}

	public boolean closeBT() {
		stopWorker = true;
		try {
			if (mmOutputStream != null)
				mmOutputStream.close();
			if (mmInputStream != null)
				mmInputStream.close();
			if (mmSocket != null)
				mmSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 
	 * @param arrayAdapter
	 */
	private void displayList(final ArrayAdapter<String> arrayAdapter) {
		AlertDialog.Builder builderSingle = new AlertDialog.Builder(mContext);
		builderSingle.setTitle("Select your device: ");
		builderSingle.setNegativeButton("cancel",
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
					}
				});
		builderSingle.setAdapter(arrayAdapter,
				new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						String strName = arrayAdapter.getItem(which);
						for (BluetoothDevice device : mmPairedDevices) {
							if (device.getName().equals(strName)) {
								mmDevice = device;
								try {
									open();
								} catch (IOException e) {
									Toast.makeText(
											mContext,
											"Bluetooth device ("
													+ mmDevice.getName() + " "
													+ mmDevice.getAddress()
													+ ") not found!",
											Toast.LENGTH_LONG).show();
									break;
								}
								break;
							}
						}
					}
				});
		builderSingle.show();
	}

	/**
	 * 
	 * @throws IOException
	 */
	private void open() throws IOException {
		UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
		mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
		mmSocket.connect();
		mmOutputStream = mmSocket.getOutputStream();
		mmInputStream = mmSocket.getInputStream();
		beginListenForData();
		mBluetoothSerialCallback.OnBluetoothSerialOpen();
	}

	public boolean isEnable() {
		if (mBluetoothAdapter == null)
			return false;
		return mBluetoothAdapter.isEnabled();
	}

	public boolean isOpen() {
		if (mmSocket == null)
			return false;
		return mmSocket.isConnected();
	}

	/**
	 * 
	 */
	private void beginListenForData() {
		stopWorker = false;
		readBuffer = new byte[1024];
		workerThread = new Thread(new Runnable() {
			public void run() {
				byte[] bufferCopy;
				while (!Thread.currentThread().isInterrupted() && !stopWorker) {
					try {
						int bytesAvailable = mmInputStream.read(readBuffer);
						// Log.d(FrskyTelemetry.LOG_TAG, "Read: " +
						// bytesAvailable);
						bufferCopy = new byte[bytesAvailable];
						System.arraycopy(readBuffer, 0, bufferCopy, 0,
								bytesAvailable);

						Message msgObj = mHandler.obtainMessage();

						Bundle b = new Bundle();
						b.putByteArray("buffer", bufferCopy);
						msgObj.setData(b);
						mHandler.sendMessage(msgObj);
					} catch (IOException ex) {
						ex.printStackTrace();
						stopWorker = true;
					}
				}
			}
		});
		workerThread.start();
	}
}
